/*    file: main.cpp
 *    desc:
 * 
 * created: 2016-04-06
 *  author: chuanjiang.zh@qq.com
 * company: 
 */

#include <stdio.h>
#include <iostream>

#include "BasicType.h"
#include "RtspCaster.h"
#include "Ffmpeg.h"
#include "SharedPtr.h"
#include "TFileUtil.h"
#include <assert.h>
#include "CLog.h"
#include "TFileWriter.h"

#include "CAudioFrameSource.h"
#include "myopus.h"
#include "TByteBuffer.h"


static bool hasPrefix(const uint8_t* data, int size)
{
    assert(size >= 4);
    if ((data[0] == 0) && (data[1] == 0))
    {
        if ((data[2] == 0) && (data[3] == 1))
        {
            return true;
        }
        if (data[2] == 1)
        {
            return true;
        }
    }
    return false;
}

class Application : public av::AVFrameSink
{
public:
    Application():
        m_handle(),
        m_format(),
        m_opus()
    {
        CLog::setLogger(CLog::COUT);
        CLog::setLogger(CLog::DEBUGWINDOW);

        av_register_all();
        avformat_network_init();

        caster_init(554);
    }

    ~Application()
    {
        close();

        caster_quit();
    }

    void open(const std::string& url)
    {
        m_fileWriter.open("out.opus");

        m_source.setSink(this);

        std::string params;
        int channels = 1;
        int freq = 8000;
        m_source.open(url, params, channels, freq, AV_SAMPLE_FMT_S16);
        
        m_format.audioCodec = MCODEC_OPUS;
        m_format.channels = channels;
        m_format.sampleRate = freq;
        m_format.audioRate = 1000000;
        caster_chl_open(&m_handle, "demo", &m_format);
    }

    void close()
    {
        m_source.close();

        if (m_handle)
        {
            caster_chl_close(m_handle);
            m_handle = NULL;
        }

        m_fileWriter.close();
    }

    virtual void onFrame(AVFrame* frame)
    {
        CLog::debug("onFrame. freq: %d, size: %d, pts: %lld\n", frame->sample_rate, frame->linesize[0], frame->pts);

        uint8_t* pcmData = frame->data[0];
        int pcmSize = frame->linesize[0];

        m_buffer.ensure(pcmSize);
        MPacket mpkt = MPacket();
        mpkt.data = m_buffer.data();

        int length = m_opus.Pcm2Opus_Enc(pcmData, pcmSize, m_buffer.data(), m_buffer.capacity());
        if (length > 0)
        {
            mpkt.data = m_buffer.data();
            mpkt.size = length;
            mpkt.type = MTYPE_AUDIO;
            mpkt.pts = frame->pts;
            mpkt.duration = pcmSize / 2;

            m_fileWriter.write(mpkt.data, mpkt.size);

            caster_chl_write_audio(m_handle, &mpkt);
        }
    }

    av::CAudioFrameSource   m_source;
    HANDLE m_handle;
    MFormat m_format;
    comn::FileWriter    m_fileWriter;
    myOpus  m_opus;
    comn::ByteBuffer    m_buffer;

};


int main(int argc, char** argv)
{
    Application app;
	
	//if (argc <= 1)
 //   {
 //       return EINVAL;
 //   }

    std::string url = "rtsp://admin:sjld16301@192.168.3.65/";
    app.open(url);

    while (true)
    {
        std::string line;
        std::getline(std::cin, line);
        if (line == "q")
        {
            break;
        }
    }

    app.close();

	return 0;
}




